﻿using Cysharp.Threading.Tasks;
using DG.Tweening;
using GameProtocol.Protocol;
using Google.Protobuf;
using Sirenix.Utilities.Editor.Expressions;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace GameLogic
{
    public class UDPClient : NetClient
    {
        protected UdpClient m_UDPClient;
        protected UDPClientHandle m_Kcp = null;
        protected IPEndPoint m_EndPoint;
        int TestFalg = -1;
        ~UDPClient()
        {
            if (m_ReceiveThread != null)
                m_ReceiveThread.Abort();
        }
        Thread m_ReceiveThread;
        public  override void Init(int receivePort, IPEndPoint sendEndPoint)
        {
            base.Init(receivePort, sendEndPoint);
            if (m_UDPClient == null)
                m_UDPClient = new UdpClient(receivePort);
            m_EndPoint = sendEndPoint;
            TestFalg = UnityEngine.Random.Range(0, 129481029);
            m_Kcp = UDPClientHandle.Create(m_UDPClient, m_EndPoint, m_ConversationID);
            m_Kcp.ReceiveCallback = OnReceived;
            m_ReceiveThread = new Thread(DoReceive);
            m_ReceiveThread.IsBackground = true;
            m_ReceiveThread.Start();
            Handshake();
        }
        public override void Disconnect()
        {
            base.Disconnect();  
        }

        public void OnDisconnected()
        {
            m_ReceiveThread.Abort();
            m_UDPClient.Close();
            m_UDPClient = null;
            m_Kcp.Close();
            m_Kcp = null;
            m_ReceiveThread = null;
        }
        public override void Clear()
        {
            base.Clear();
            m_ReceiveEvents.Clear();
            OnDisconnected();
        }
        public override void Handshake()
        {
            ConnectRqrData data = new ConnectRqrData();
            data.ConversationID = m_ConversationID;
            Send(CSMsgId.ConnectRqr, data.ToByteArray());
            DOVirtual.DelayedCall(1, () =>
            {
                if (m_Kcp != null && !m_Kcp.HasHandShake)
                {
                    Handshake();
                    UnityEngine.Debug.Log("尝试连接服务器失败，正在重新连接");
                }
            });
        }
        void OnConnectRsp(IPEndPoint addr, byte[] data)
        {
            var rspData = ConnectRspData.Parser.ParseFrom(data);
            if (m_Kcp != null && rspData != null)
            {
                m_Kcp.HasHandShake = true;
                m_HasHandshake = true;
                UnityEngine.Debug.Log("服务器连接成功！");
            }
        }
        public override void Send(GameProtocol.Protocol.CSMsgId id, byte[] data)
        {
            MessageContent content = new MessageContent();
            if (data != null)
                content.Data = ByteString.CopyFrom(data);
            content.MsgID = id;

            var sendData = content.ToByteArray();
            Send(sendData, sendData.Length);
        }
        protected override void Send(byte[] data, int length)
        {
            if (m_Kcp != null && m_Kcp.HasHandShake)
                m_Kcp.Send(data, length);
            else
                m_UDPClient.SendAsync(data, data.Length, m_EndPoint);
        }
        protected void RecvOriginData(IPEndPoint endPoint, byte[] data)
        {
            var msg = MessageContent.Parser.ParseFrom(data);
            if (msg != null && m_ReceiveEvents.ContainsKey(msg.MsgID))
            {
                var subData = msg.Data.ToByteArray();
                if (msg.MsgID == CSMsgId.ConnectRsp)
                    OnConnectRsp(endPoint, subData);
                m_ReceiveEvents[msg.MsgID].Invoke(endPoint, subData);
            }
        }
         void DoReceive()
        {
            Debug.LogWarning("DoReceive:" + TestFalg);
            while (m_UDPClient != null )
            {
                byte[] data = null;
                try
                {
                    data = m_UDPClient.Receive(ref m_EndPoint);
                }
                catch (Exception e)
                {
                    UnityEngine.Debug.LogWarning("接收数据已取消");
                }
                if (data != null)
                {
                    //var endPoint = res.RemoteEndPoint;
                    if (m_Kcp != null && m_Kcp.HasHandShake)
                    {
                        m_Kcp.Input(data);
                    }
                    else
                        RecvOriginData(m_EndPoint, data);
                }
            }
        }
        public override string GetLocalIP()
        {
            var endPoint = (IPEndPoint)m_UDPClient.Client.LocalEndPoint;
            return endPoint.Address.ToString();
        }
        protected override  void OnReceived(IPEndPoint ep , byte[] data, int offset, int length)
        {
            base.OnReceived(ep,data, offset, length);
            var msg = MessageContent.Parser.ParseFrom(data, offset, length);
            if (msg != null && m_ReceiveEvents.ContainsKey(msg.MsgID))
            {
                var subData = msg.Data.ToByteArray();
                var rspData = ConnectRspData.Parser.ParseFrom(subData);
                try
                {
                    m_ReceiveEvents[msg.MsgID].Invoke(m_EndPoint, subData);
                }catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
        }
    }
}
